home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / TEXTILE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  9.0 KB  |  366 lines

  1. /*
  2. ** cc -o textile textile.c -lGLU -lGL -lglut -lXmu -lX11 -lm
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #include <string.h>
  8. #include <GL/glut.h>
  9. #include "texture.h"
  10.  
  11. int maxTextureSize;
  12. int maxTextureLevel;
  13.  
  14. int imageWidth, imageHeight;
  15. GLubyte *imageData;
  16.  
  17. int texWidthLevel0, texHeightLevel0;
  18. int texWidthTiles, texHeightTiles;
  19. GLubyte **texImageLevel;
  20.  
  21. GLboolean useBorder = GL_TRUE;
  22. GLboolean useClamp = GL_TRUE;
  23. GLboolean useLinear = GL_TRUE;
  24. GLboolean useMipmap = GL_TRUE;
  25. GLboolean useTextureTiling = GL_TRUE;
  26.  
  27. /* (int)floor(log2(a)) */
  28. static int
  29. iflog2(unsigned int a)
  30. {
  31.     int x = 0;
  32.     while (a >>= 1) ++x;
  33.     return x;
  34. }
  35.  
  36. static void
  37. initialize(void)
  38. {
  39.     glMatrixMode(GL_PROJECTION);
  40.     glLoadIdentity();
  41.     glFrustum(-0.5, 0.5, -0.5, 0.5, 0.5, 1.5);
  42.  
  43.     glMatrixMode(GL_MODELVIEW);
  44.     glLoadIdentity();
  45.     glTranslatef(0, 0, -0.90);
  46.     glRotatef( 45.0, 0, 1, 0);
  47.     glTranslatef(-0.5, -0.5, 0.0);
  48.  
  49. #if 0
  50.     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
  51. #else
  52.     maxTextureSize = 32;
  53. #endif
  54.     maxTextureLevel = iflog2(maxTextureSize);
  55.  
  56.     texImageLevel = (GLubyte **) calloc(maxTextureLevel+1, sizeof(GLubyte *));
  57.     if (texImageLevel == NULL) {
  58.     fprintf(stderr, "texture level image allocation failed\n");
  59.     exit(EXIT_FAILURE);
  60.     }
  61.     glClearColor(0.1, 0.1, 0.1, 0.1);
  62. }
  63.  
  64. static void
  65. imgLoad(char *filename_in, int *w_out, int *h_out, GLubyte **img_out)
  66. {
  67.     int comp;
  68.  
  69.     *img_out = (GLubyte *)read_texture(filename_in, w_out, h_out, &comp);
  70.     if (img_out == NULL) {
  71.     fprintf(stderr, "unable to read %s\n", filename_in);
  72.     exit(EXIT_FAILURE);
  73.     }
  74.     if (comp != 3 && comp != 4) {
  75.     fprintf(stderr, "%s: image is not RGB or RGBA\n", filename_in);
  76.     exit(EXIT_FAILURE);
  77.     }
  78. }
  79.  
  80. static void
  81. buildMipmaps(void)
  82. {
  83.     int level, levelWidth, levelHeight;
  84.  
  85.     if (useTextureTiling) {
  86.     int width2 = iflog2(imageWidth);
  87.     int height2 = iflog2(imageHeight);
  88.  
  89.     width2 = (width2 > maxTextureLevel) ? width2 : maxTextureLevel;
  90.     height2 = (height2 > maxTextureLevel) ? height2 : maxTextureLevel;
  91.  
  92.     texWidthLevel0 = 1 << width2;
  93.     texHeightLevel0 = 1 << height2;
  94.     texWidthTiles = texWidthLevel0 >> maxTextureLevel;
  95.     texHeightTiles = texHeightLevel0 >> maxTextureLevel;
  96.     } else {
  97.     texWidthLevel0 = maxTextureSize;
  98.     texHeightLevel0 = maxTextureSize;
  99.     texWidthTiles = 1;
  100.     texHeightTiles = 1;
  101.     }
  102.  
  103.     texImageLevel[0] = (GLubyte *)
  104.     calloc(1, (texWidthLevel0+2)*(texHeightLevel0+2)*4*sizeof(GLubyte));
  105.  
  106.     glPixelStorei(GL_PACK_ROW_LENGTH, texWidthLevel0+2);
  107.     glPixelStorei(GL_PACK_SKIP_PIXELS, 1);
  108.     glPixelStorei(GL_PACK_SKIP_ROWS, 1);
  109.  
  110.     gluScaleImage(GL_RGBA, imageWidth, imageHeight,
  111.           GL_UNSIGNED_BYTE, imageData,
  112.           texWidthLevel0, texHeightLevel0,
  113.           GL_UNSIGNED_BYTE, texImageLevel[0]);
  114.  
  115.     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 1);
  116.     glPixelStorei(GL_UNPACK_SKIP_ROWS, 1);
  117.  
  118.     levelWidth = texWidthLevel0;
  119.     levelHeight = texHeightLevel0;
  120.     for (level=0; level<maxTextureLevel; ++level) {
  121.     int newLevelWidth = (levelWidth > 1) ? levelWidth / 2 : 1;
  122.     int newLevelHeight = (levelHeight > 1) ? levelHeight / 2 : 1;
  123.     
  124.     texImageLevel[level+1] = (GLubyte *)
  125.         calloc(1, (newLevelWidth+2)*(newLevelHeight+2)*4*sizeof(GLubyte));
  126.  
  127.     glPixelStorei(GL_PACK_ROW_LENGTH, newLevelWidth+2);
  128.     glPixelStorei(GL_UNPACK_ROW_LENGTH, levelWidth+2);
  129.  
  130.     gluScaleImage(GL_RGBA, levelWidth, levelHeight,
  131.               GL_UNSIGNED_BYTE, texImageLevel[level],
  132.               newLevelWidth, newLevelHeight,
  133.               GL_UNSIGNED_BYTE, texImageLevel[level+1]);
  134.  
  135.     levelWidth = newLevelWidth;
  136.     levelHeight = newLevelHeight;
  137.     }
  138.  
  139.     glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  140.     glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
  141.     glPixelStorei(GL_PACK_SKIP_ROWS, 0);
  142.  
  143.     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  144.     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  145.     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  146. }
  147.  
  148. static void
  149. freeMipmaps(void)
  150. {
  151.     int i;
  152.  
  153.     for (i=0; i<=maxTextureLevel; ++i) {
  154.     if (texImageLevel[i] != NULL) {
  155.         free(texImageLevel[i]);
  156.         texImageLevel[i] = NULL;
  157.     }
  158.     }
  159. }
  160.  
  161. static void
  162. loadTile(int row, int col)
  163. {
  164.     int border = useBorder ? 1 : 0;
  165.     int level, levelWidth, levelHeight;
  166.  
  167.     levelWidth = texWidthLevel0;
  168.     levelHeight = texHeightLevel0;
  169.     for (level=0; level<=maxTextureLevel; ++level) {
  170.     int tileWidth = levelWidth / texWidthTiles;
  171.     int tileHeight = levelHeight / texHeightTiles;
  172.     int skipPixels = col * tileWidth + (1 - border);
  173.     int skipRows = row * tileHeight + (1 - border);
  174.  
  175.     glPixelStorei(GL_UNPACK_ROW_LENGTH, levelWidth+2);
  176.     glPixelStorei(GL_UNPACK_SKIP_PIXELS, skipPixels);
  177.     glPixelStorei(GL_UNPACK_SKIP_ROWS, skipRows);
  178.  
  179.     glTexImage2D(GL_TEXTURE_2D, level, 4,
  180.              tileWidth + 2*border, tileHeight + 2*border,
  181.              border, GL_RGBA, GL_UNSIGNED_BYTE, texImageLevel[level]);
  182.     
  183.     if (levelWidth > 1) levelWidth = levelWidth / 2;
  184.     if (levelHeight > 1) levelHeight = levelHeight / 2;
  185.     }
  186.  
  187.     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  188.     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  189.     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  190. }
  191.  
  192. static void
  193. redraw(void)
  194. {
  195.     GLenum minFilterMode, magFilterMode, wrapMode;
  196.     char *minFilterName, *magFilterName, *wrapName;
  197.     int i, j;
  198.  
  199.     if (useLinear) {
  200.     if (useMipmap) {
  201.         minFilterMode = GL_LINEAR_MIPMAP_LINEAR;
  202.         minFilterName = "LINEAR_MIPMAP_LINEAR";
  203.     } else {
  204.         minFilterMode = GL_LINEAR;
  205.         minFilterName = "LINEAR";
  206.     }
  207.     magFilterMode = GL_LINEAR;
  208.     magFilterName = "LINEAR";
  209.     } else {
  210.     if (useMipmap) {
  211.         minFilterMode = GL_NEAREST_MIPMAP_LINEAR;
  212.         minFilterName = "NEAREST_MIPMAP_LINEAR";
  213.     } else {
  214.         minFilterMode = GL_NEAREST;
  215.         minFilterName = "NEAREST";
  216.     }
  217.     magFilterMode = GL_NEAREST;
  218.     magFilterName = "NEAREST";
  219.     }
  220.  
  221.     if (useClamp) {
  222.     wrapMode = GL_CLAMP;
  223.     wrapName = "CLAMP";
  224.     } else {
  225.     wrapMode = GL_REPEAT;
  226.     wrapName = "REPEAT";
  227.     }
  228.  
  229.     fprintf(stderr, "tile(%s) ", useTextureTiling ? "yes" : "no");
  230.     fprintf(stderr, "border(%s) ", useBorder ? "yes" : "no");
  231.     fprintf(stderr, "filter(%s, %s) ", minFilterName, magFilterName);
  232.     fprintf(stderr, "wrap(%s) ", wrapName);
  233.     fprintf(stderr, "\n");
  234.  
  235.     glClear(GL_COLOR_BUFFER_BIT);
  236.  
  237.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  238.  
  239.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilterMode);
  240.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilterMode);
  241.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
  242.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
  243.  
  244.     buildMipmaps();
  245.  
  246.     glEnable(GL_TEXTURE_2D);
  247.  
  248.     for (i=0; i<texHeightTiles; ++i) {
  249.     float ySize = 1.0 / texHeightTiles;
  250.     float y0 = i * ySize;
  251.     float y1 = y0 + ySize;
  252.  
  253.     for (j=0; j<texWidthTiles; ++j) {
  254.         float xSize = 1.0 / texWidthTiles;
  255.         float x0 = j * xSize;
  256.         float x1 = x0 + xSize;
  257.  
  258.         loadTile(i, j);
  259.  
  260.         glBegin(GL_TRIANGLE_STRIP);
  261.         glTexCoord2f(0.0, 1.0); glVertex2f(x0, y1);
  262.         glTexCoord2f(0.0, 0.0); glVertex2f(x0, y0);
  263.         glTexCoord2f(1.0, 1.0); glVertex2f(x1, y1);
  264.         glTexCoord2f(1.0, 0.0); glVertex2f(x1, y0);
  265.         glEnd();
  266.     }
  267.     }
  268.  
  269.     glDisable(GL_TEXTURE_2D);
  270.  
  271.     freeMipmaps();
  272. }
  273.  
  274. static void
  275. usage(char *argv[])
  276. {
  277.     fprintf(stderr, "\n");
  278.     fprintf(stderr, "usage: %s [ options ] filename\n", argv[0]);
  279.     fprintf(stderr, "\n");
  280.     fprintf(stderr, "    Demonstrates using texture borders\n");
  281.     fprintf(stderr, "    to tile a large texture\n");
  282.     fprintf(stderr, "\n");
  283.     fprintf(stderr, "  Options:\n");
  284.     fprintf(stderr, "    -sb  single buffered\n");
  285.     fprintf(stderr, "    -db  double buffered\n");
  286.     fprintf(stderr, "\n");
  287. }
  288.  
  289. /*ARGSUSED1*/
  290. void
  291. key(unsigned char key, int x, int y) {
  292.     switch(key) {
  293.     case '\033': exit(EXIT_SUCCESS); break;
  294.     case 'b':    useBorder = !useBorder; break;
  295.     case 'w':    useClamp = !useClamp; break;
  296.     case 'l':    useLinear = !useLinear; break;
  297.     case 'm':    useMipmap = !useMipmap; break;
  298.     case 't':    useTextureTiling = !useTextureTiling; break;
  299.     default:    break;
  300.     }
  301.     glutPostRedisplay();
  302. }
  303.  
  304. int doubleBuffered = GL_FALSE;
  305.  
  306. void display(void) {
  307.     GLenum error;
  308.     redraw();
  309.     if (doubleBuffered)
  310.     glutSwapBuffers();
  311.     else
  312.     glFlush();
  313.     while ((error = glGetError()) != GL_NO_ERROR) {
  314.     fprintf(stderr, "Error: %s\n", (char *) gluErrorString(error));
  315.     }
  316. }
  317.  
  318. void
  319. reshape(int w, int h) {
  320.     glViewport(0, 0, w, h);
  321. }
  322.  
  323. int
  324. main(int argc, char *argv[])
  325. {
  326.     char *name = "Texture Tiling Test";
  327.     int width = 300, height = 300;
  328.     char *filename = NULL;
  329.     int i;
  330.  
  331.     glutInitWindowSize(width, height);
  332.     glutInit(&argc, argv);
  333.  
  334.     for (i=1; i<argc; ++i) {
  335.     if (!strcmp("-sb", argv[i])) {
  336.         doubleBuffered = GL_FALSE;
  337.  
  338.     } else if (!strcmp("-db", argv[i])) {
  339.         doubleBuffered = GL_TRUE;
  340.  
  341.     } else if (argv[i][0] != '-' && i==argc-1) {
  342.         filename = argv[i];
  343.  
  344.     } else {
  345.         usage(argv);
  346.         exit(EXIT_FAILURE);
  347.     }
  348.     }
  349.  
  350.     if (filename == NULL) {
  351.     usage(argv);
  352.     exit(EXIT_FAILURE);
  353.     }
  354.  
  355.     imgLoad(filename, &imageWidth, &imageHeight, &imageData);
  356.  
  357.     glutInitDisplayMode(GLUT_RGBA|(doubleBuffered ? GLUT_DOUBLE : 0));
  358.     (void)glutCreateWindow(name);
  359.     glutDisplayFunc(display);
  360.     glutReshapeFunc(reshape);
  361.     glutKeyboardFunc(key);
  362.     initialize();
  363.     glutMainLoop();
  364.     return 0;
  365. }
  366.